home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 1
/
Nebula One.iso
/
Communications
/
pop3d
/
Source
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-06-07
|
10KB
|
376 lines
/*
* pop3d - IP/TCP/POP3 server for UNIX 4.3BSD
* Post Office Protocol - Version 3 (RFC1225)
*
* (C) Copyright 1991 Regents of the University of California
*
* Permission to use, copy, modify, and distribute this program
* for any purpose and without fee is hereby granted, provided
* that this copyright and permission notice appear on all copies
* and supporting documentation, the name of University of California
* not be used in advertising or publicity pertaining to distribution
* of the program without specific prior permission, and notice be
* given in supporting documentation that copying and distribution is
* by permission of the University of California.
* The University of California makes no representations about
* the suitability of this software for any purpose. It is provided
* "as is" without express or implied warranty.
*
* Katie Stevens
* dkstevens@ucdavis.edu
* Information Technology -- Campus Access Point
* University of California, Davis
*
**************************************
*
* main.c
*
* REVISIONS:
* 02-27-90 [ks] original implementation
* 1.000 03-04-90 [ks]
* 1.001 06-24-90 [ks] implement optional TOP command
* 1.002 07-22-91 [ks] -- reset index counter after folder rewind
* in fld_release (Thanks to John Briggs,
* vaxs09@vitro.com, Vitro Corporation,
* Silver Spring, MD for finding this bug!)
* -- set umask() value explicitly (Thanks to
* Vikas Aggarwal, JvNCnet, Princeton, NJ
* for suggesting this)
* 1.003 03-92 [ks] close mailbox before return from main()
* 1.004 11-13-91 [ks] leave original mailbox intact during POP
* session (Thanks to Dave Cooley,
* dwcooley@colby.edu for suggesting this)
*/
#include <stdio.h>
#include <signal.h>
#include <ctype.h>
#include <sys/param.h>
#include "pop3.h"
#define VERSION "1.004"
#define REVDATE "January, 1992"
char *svr_hostname; /* Hostname of POP3 server */
char svr_buf[SVR_BUFSIZ+2]; /* Buffer for server I/O */
char cli_user[CLI_BUFSIZ]; /* Save client username */
static char *svr_invalid = "-ERR Invalid command; valid commands:";
#ifdef DEBUG
FILE *logfp = NULL; /* File for recording session */
#endif
/* Routines in this file */
static void initialize();
static void svr_timeout();
static void int_hangup();
static void int_progerr();
static int svr_auth();
static int svr_pass();
static int svr_trans();
static int svr_fold();
static int svr_shutdown();
/**************************************************************************/
/* Initialize POP3 server */
static void
initialize()
{
char buf[MAXHOSTNAMELEN+1];
/* File permissions for owner only */
umask(077); /* [1.002] */
#ifdef DEBUG
/* Prepare log file */
logfp = fopen(LOGFILE,"w");
fprintf(logfp,"POP3 server startup; version %s (%s)\n",
VERSION,REVDATE);
#endif
/* Get our hostname */
gethostname(buf,MAXHOSTNAMELEN);
svr_hostname = malloc(strlen(buf) + 1);
if (svr_hostname == NULL)
fail(FAIL_OUT_OF_MEMORY);
strcpy(svr_hostname,buf);
/* Handle process signals ourself */
signal(SIGALRM, svr_timeout); /* timer expiration */
signal(SIGHUP, int_hangup); /* socket signals */
signal(SIGURG, int_hangup);
signal(SIGTERM, int_hangup);
#ifdef LINUX
# ifdef SIGBUS
signal(SIGBUS, int_progerr); /* fatal program errors */
# endif
#endif
signal(SIGSEGV, int_progerr);
signal(SIGILL, int_progerr);
signal(SIGIOT, int_progerr);
}
/* Timeout while waiting for next client command */
static void
svr_timeout()
{
fld_release(); /* Release mailbox folder */
fail(FAIL_LOST_CLIENT); /* Exit POP3 server */
}
/* Timeout while waiting for next client command */
static void
int_hangup()
{
fld_release(); /* Release mailbox folder */
fail(FAIL_HANGUP); /* Exit POP3 server */
}
/* Timeout while waiting for next client command */
static void
int_progerr()
{
fld_release(); /* Release mailbox folder */
fail(FAIL_PROGERR); /* Exit POP3 server */
}
/**************************************************************************/
/* Server Authentification State; process client USER command */
static int
svr_auth(state,inbuf)
int state;
char *inbuf;
{
if (strncmp(inbuf,"quit",4) == 0)
return(svr_shutdown());
/* Expecting USER command */
if (strncmp(inbuf,"user",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
strcpy(cli_user,inbuf);
strcpy(svr_buf,"+OK please send PASS command\r\n");
state = SVR_PASS_STATE;
} else {
sprintf(svr_buf,"%s USER, QUIT\r\n",svr_invalid);
}
return(state);
}
/* Server Password State; process client PASS command */
static int
svr_pass(state,inbuf)
int state;
char *inbuf;
{
int cnt;
if (strncmp(inbuf,"quit",4) == 0)
return(svr_shutdown());
/* Expecting PASS command */
if (strncmp(inbuf,"pass",4) != 0) {
sprintf(svr_buf,"%s PASS, QUIT\r\n",svr_invalid);
return(state);
}
/* Verify usercode/password pair */
inbuf += 4;
EATSPACE(inbuf);
if (verify_user(cli_user,inbuf) == -1) {
strcpy(svr_buf,"-ERR invalid usercode or password, please try again\r\n");
return(SVR_AUTH_STATE);
}
strcpy(svr_buf,DEF_MAIL_DIR);
strcat(svr_buf,cli_user);
return(fld_fromsp(svr_buf));
}
/* Server Transaction State; process client mailbox command */
static int
svr_trans(state,inbuf)
int state;
char *inbuf;
{
int msgnum;
if (strncmp(inbuf,"quit",4) == 0)
return(svr_shutdown());
/* Expecting mailbox command */
if (strncmp(inbuf,"dele",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR)
sprintf(svr_buf,"-ERR message number required (e.g. DELE 1)\r\n");
else
fld_delete(atoi(inbuf));
} else if (strncmp(inbuf,"host",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR)
sprintf(svr_buf,"-ERR must specify hostname\r\n");
else
state = fld_bsmtp(inbuf);
} else if (strncmp(inbuf,"last",4) == 0) {
fld_last();
} else if (strncmp(inbuf,"list",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR)
fld_list(-1);
else
fld_list(atoi(inbuf));
} else if (strncmp(inbuf,"mbox",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR)
sprintf(svr_buf,"-ERR must specify mailbox filename\r\n");
else
state = fld_fromsp(inbuf);
} else if (strncmp(inbuf,"noop",4) == 0) {
strcpy(svr_buf,"+OK\r\n");
} else if (strncmp(inbuf,"retr",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR) {
sprintf(svr_buf,"-ERR message number required (e.g. RETR 1)\r\n");
} else
fld_retr(atoi(inbuf),-1);
} else if (strncmp(inbuf,"rset",4) == 0) {
fld_reset();
} else if (strncmp(inbuf,"stat",4) == 0) {
fld_stat();
} else if (strncmp(inbuf,"top",3) == 0) {
inbuf += 3;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR) {
sprintf(svr_buf,"-ERR message number and line count required (e.g. TOP 1 7)\r\n");
} else {
msgnum = atoi(inbuf);
while (!isspace(*inbuf)) ++inbuf;
EATSPACE(inbuf);
if (*inbuf == NULL_CHAR)
sprintf(svr_buf,"-ERR line count required (e.g. TOP 1 7)\r\n");
else
fld_retr(msgnum,atoi(inbuf));
}
} else {
sprintf(svr_buf,
"%s DELE, HOST, LAST, LIST, MBOX, NOOP, RETR, RSET, STAT, TOP or QUIT\r\n",
svr_invalid);
}
return(state);
}
/* Server Folder State; need to open another folder */
static int
svr_fold(state,inbuf)
int state;
char *inbuf;
{
if (strncmp(inbuf,"quit",4) == 0)
return(svr_shutdown());
if (strncmp(inbuf,"host",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
state = fld_bsmtp(inbuf);
} else if (strncmp(inbuf,"mbox",4) == 0) {
inbuf += 4;
EATSPACE(inbuf);
state = fld_fromsp(inbuf);
} else if (strncmp(inbuf,"noop",4) == 0) {
strcpy(svr_buf,"+OK\r\n");
} else {
sprintf(svr_buf,"%s HOST, MBOX, NOOP or QUIT\r\n",svr_invalid);
}
return(state);
}
/* Prepare to shutdown POP3 server */
static int
svr_shutdown()
{
fld_release();
sprintf(svr_buf,"+OK %s POP3 Server (Version %s) shutdown.\r\n",
svr_hostname,VERSION);
return(SVR_DONE_STATE);
}
/**************************************/
void
svr_data_out(buf)
char *buf;
{
/* Send out response to client */
alarm(SVR_TIMEOUT_SEND);
fputs(buf,stdout);
fflush(stdout);
alarm(0);
}
/**************************************************************************/
main()
{
int svr_state = SVR_LISTEN_STATE; /* State of POP3 server */
char cli_buf[CLI_BUFSIZ]; /* Buffer for client cmds */
initialize();
fprintf(stdout,"+OK %s POP3 Server (Version %s) ready.\r\n",
svr_hostname,VERSION);
fflush(stdout);
svr_state = SVR_AUTH_STATE;
for ( ; ; ) {
/* Wait for command from client */
alarm(SVR_TIMEOUT_CLI);
if (fgetl(cli_buf,CLI_BUFSIZ,stdin) == NULL)
break;
alarm(0);
/* Take action on client command */
cmd_prepare(cli_buf);
#ifdef DEBUG
if ((cli_buf[0] == 'p')||(cli_buf[0] == 'P'))
fprintf(logfp,"CLI: PASS\n",cli_buf);
else
fprintf(logfp,"CLI: %s\n",cli_buf);
#endif
switch(svr_state) {
case SVR_AUTH_STATE: /* Expecting USER command */
svr_state = svr_auth(svr_state,cli_buf);
break;
case SVR_PASS_STATE: /* Expecting PASS command */
svr_state = svr_pass(svr_state,cli_buf);
break;
case SVR_TRANS_STATE: /* Expecting mailbox command */
svr_state = svr_trans(svr_state,cli_buf);
break;
case SVR_FOLD_STATE: /* Need to open another mailbox */
svr_state = svr_fold(svr_state,cli_buf);
break;
default:
fail(FAIL_CONFUSION); /* Wont return */
break;
}
#ifdef DEBUG
fprintf(logfp,"SVR: %s",svr_buf);
#endif
/* Send out response to client */
alarm(SVR_TIMEOUT_SEND);
fputs(svr_buf,stdout);
fflush(stdout);
alarm(0);
if (ferror(stdout))
break;
/* Exit when server has sent goodbye */
if (svr_state == SVR_DONE_STATE)
break;
}
fld_release(); /* [1.003] Make sure folder is released */
exit(0);
}